/* 
 * Cashbox is the legal property of its developers, whose names are listed in the copyright file included
 * with this source distribution.
 * 
 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
 * General Public License as published by the Free Software Foundation; either version 2 of the License,
 * or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
 * Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with this program; if not,
 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#import <Cashbox/CBControllerProtocol.h>
#import <Cashbox/CBAccount.h>
#import <Cashbox/CBTransaction.h>
#import <Cashbox/CBLabel.h>
#import <Cashbox/ColorListColors.h>
#import <Cashbox/CBPlugin.h>
#import <Cashbox/CBModelExtensionPlugin.h>
#import <Cashbox/CBInterfaceControllerProtocol.h>
#import <Cashbox/CBPluginControllerProtocol.h>

#import "CBDataController.h"
#import "CBImporter.h"
#import "CBImportPanelController.h"


#ifdef UNIT_TEST
	#define STORE_FILENAME	@"unittest.xml"
	#define STORE_TYPE		NSXMLStoreType
	#define LOG_DIRECTORY	@"New Cashbox"
#else
	#ifdef RELEASE
		#define STORE_FILENAME	@"data.sqlite"
		#define STORE_TYPE		NSSQLiteStoreType
		#define LOG_DIRECTORY	@"New Cashbox"
	#else
//		#define STORE_FILENAME	@"data.xml"
//		#define STORE_TYPE		NSXMLStoreType
//		#define LOG_DIRECTORY	@"New Cashbox"
		#define STORE_FILENAME	@"test_data.sqlite"
		#define STORE_TYPE		NSSQLiteStoreType
		#define LOG_DIRECTORY	@"New Cashbox"
	#endif
#endif

@interface CBDataController (Private)
+ (NSString *)_applicationSupportFolder;
- (void)setupInitialDataIfNeeded;
@end

@implementation CBDataController

- (id)init {
	if (self = [super init]) {
		ald = nil;
		moc = nil;
		mom = nil;
	}
	return self;
}

- (void)controllerDidLoad {
	[self setupInitialDataIfNeeded];
}

- (void)controllerWillClose {
	[self saveData:nil];
}

- (IBAction)saveData:(id)sender {
	// save the data
	NSError *err = nil;
	[[self managedObjectContext] save:&err];
	if (err) {
		[[NSApp keyWindow] presentError:err];
		if ([err code] == NSValidationMultipleErrorsError) {
			NSArray *detailedErrors = [[err userInfo] objectForKey:NSDetailedErrorsKey];
			for (NSError *e in detailedErrors) { FSLog(@"%@", e); }
		} else {
			FSLog(@"%@", err);
		}
#ifdef UNIT_TEST
		[NSException raise:@"Error saving" format:@"Error saving: %@", err];
#endif
	}	
}

#ifdef UNIT_TEST
+ (void)destroyData {
	[[NSFileManager defaultManager] removeFileAtPath:[[self _applicationSupportFolder]
													  stringByAppendingPathComponent:STORE_FILENAME]
											 handler:nil];
}
#endif

#pragma mark importing data
// ----------------------------------------------------------------------------------------------------
// importing data
// ----------------------------------------------------------------------------------------------------

- (void)importFile:(NSString *)path {
#ifndef UNIT_TEST
	NSString *extension = [[path pathExtension] lowercaseString];
	CBImporter *importer = [CBImporter importerForExtension:extension];	
	if (importer) {
		NSWindow *mainWindow = [[cashbox interfaceController] mainWindow];
		if ([mainWindow isVisible]) {
			[CBImportPanelController beginSheetWithDelegate:self
												   importer:importer
											 modalForWindow:[[cashbox interfaceController] mainWindow]];
		} else { [CBImportPanelController runWithDelegate:cashbox importer:importer]; }
		[importer readFile:path];
	}
#endif
}

#pragma mark initial setup
// ----------------------------------------------------------------------------------------------------
// initial setup
// ----------------------------------------------------------------------------------------------------

- (void)setupInitialDataIfNeeded {
	BOOL allSetupNeeded = ![[NSFileManager defaultManager]
							fileExistsAtPath:[[self applicationSupportFolder]
											  stringByAppendingPathComponent:STORE_FILENAME]];
	BOOL labelSetupNeeded = allSetupNeeded;
	
	if (!labelSetupNeeded) {
		[self managedObjectContext]; // make sure the managed object context has been set up
		NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
		[request setEntity:[CBLabel entity]];
		[request setFetchLimit:1];
		labelSetupNeeded = [[[self managedObjectContext] executeFetchRequest:request error:NULL] count] == 0;
	}
		
	if (labelSetupNeeded) {
		CBLabel *label;
		
		label = [[[CBLabel alloc] initWithIndex:0
			  andInsertIntoManagedObjectContext:[self managedObjectContext]] autorelease];
		[label setName:@"Rent"];
		[label setColor:COLOR_LIST_COLOR_1];

		label = [[[CBLabel alloc] initWithIndex:1
			  andInsertIntoManagedObjectContext:[self managedObjectContext]] autorelease];
		[label setName:@"Food"];
		[label setColor:COLOR_LIST_COLOR_2];

		label = [[[CBLabel alloc] initWithIndex:2
			  andInsertIntoManagedObjectContext:[self managedObjectContext]] autorelease];
		[label setName:@"Gas"];
		[label setColor:COLOR_LIST_COLOR_3];
	}

}

+ (NSString *)_applicationSupportFolder {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
    NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : NSTemporaryDirectory();
    return [basePath stringByAppendingPathComponent:LOG_DIRECTORY];
}

- (NSString *)applicationSupportFolder {
	return [[self class] _applicationSupportFolder];
}

- (NSManagedObjectModel *)builtInManagedObjectModel {
	if (bimom != nil) { return bimom; }	
	NSArray *bundles = [NSArray arrayWithObjects:[NSBundle mainBundle],
												 [NSBundle bundleForClass:[CBPlugin class]], nil];
    bimom = [[NSManagedObjectModel mergedModelFromBundles:bundles] retain];
    return bimom;	
}

- (NSManagedObjectModel *)managedObjectModel {
	if (mom != nil) { return mom; }
	
	NSMutableArray *models = [NSMutableArray arrayWithObject:[self builtInManagedObjectModel]];
	NSEnumerator *pluginEnumerator = [[[cashbox pluginController] plugins] objectEnumerator];
	CBPlugin *plugin;
	while ((plugin = [pluginEnumerator nextObject])) {
		if ([plugin isKindOfClass:[CBModelExtensionPlugin class]]) {
			[models addObject:[(CBModelExtensionPlugin *)plugin model]];
		}
	}
    mom = [[NSManagedObjectModel modelByMergingModels:models] retain];
    return mom;
}

- (NSManagedObjectContext *)managedObjectContext {

	if (moc != nil) { return moc; }

	NSError *error;
	NSString *applicationSupportFolder = [self applicationSupportFolder];
    if ( ![[NSFileManager defaultManager] fileExistsAtPath:applicationSupportFolder isDirectory:NULL] ) {
        [[NSFileManager defaultManager] createDirectoryAtPath:applicationSupportFolder attributes:nil];
    }
	
	NSURL *url = [NSURL fileURLWithPath:
				  [applicationSupportFolder stringByAppendingPathComponent:STORE_FILENAME]];
	NSPersistentStoreCoordinator *coordinator =
		[[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
	if (![coordinator addPersistentStoreWithType:STORE_TYPE
								   configuration:nil
											 URL:url
										 options:nil
										   error:&error]) {
		NSLog(@"Store Configuration Failure\n%@",
			  ([error localizedDescription] != nil) ?
			  [error localizedDescription] : @"Unknown Error");

		NSAlert *theAlert = [NSAlert alertWithError:error];
		int button = [theAlert runModal];
		if (button != NSAlertFirstButtonReturn) {
			// handle
			exit(1);
		}
	}
	
	moc = [[NSManagedObjectContext alloc] init];
	[moc setPersistentStoreCoordinator:coordinator];
	
	return moc;
}
@end
